
#pragma once

#include "qlrules.h"

struct ReaderContext;

typedef struct Relation
{
    Id *                rel_id;
    unsigned int        args_count;
} Relation;

#define QL_MAX_RELATIONS    4

typedef struct RelationArray
{
    Relation            rel[QL_MAX_RELATIONS];
    size_t              size;
} RelationArray;


/*
 * pair identifier->object
 */
typedef struct
{
    Id *                var;
    Obj *               value;
} IdObjPair;

/*
 * pairs id-obj
 */
typedef struct
{
    size_t              size;
    size_t              allocated;
    IdObjPair *         pairs;
} Vars;

#define QL_IDOBJ_PAIRS_ARR_GROW_SIZE    1024

/*
 * primary context related to the rule-driven engine
 */
struct RuleEngineContext
{
    AllocContext *  alloc_ctx;

    /*
     * evaluator used when interpreting
     */
    EvalContext *   eval;

    /*
     * this is to support variables
     */
    Vars            vars;

    /*
     * default - or system namespace, all the built-in functions resides at
     */
    Id *            default_ns;

    /*
     * reader used while reading current stream
     */
    struct ReaderContext * current_reader;

    /*
     * raw list of static rules
     * e.g. ( (is A B) (have B C) (is C F) )
     */
    List *          static_rules;

    /*
     * raw list of dynamic rules
     * e.g. ( ((pattern1) (action1)) ((pattern2) (action2)) ... )
     */
    List *          dynamic_rules;

    /*
     * contains Relations traits
     */
    RelationArray   relations;

};

void
setvar( RuleEngineContext * r, Id * var, Obj * value );

/*
 * returns a value associated with the var given, 0 returns if there are no value associated
 */
Obj *
getvar( RuleEngineContext * r, Id * var );


void initialize_vars( RuleEngineContext * r );

void free_vars( RuleEngineContext * re );


void initialize_functions( RuleEngineContext * re );

void free_functions( RuleEngineContext * re );


/*
 * initializes predefined (built-in) relations, such as `is' and `have'
 */
void
add_predefined_relations( RuleEngineContext * r );
